
import {
  Component, OnInit, Input, ViewChild, Output, EventEmitter,
  TemplateRef, AfterViewInit, Injector, ChangeDetectorRef, HostBinding, NgZone, OnDestroy
} from '@angular/core';
import { TreeTableComponent, TreeNode } from '@farris/ui-treetable';
import { FieldTreeTableService } from './field-treetable/field-treetable.service';
import { NotifyService } from '@farris/ui-notify';
import { FieldTreeTableComponent } from './field-treetable/field-treetable.component';
import { constants, ContainerOptions, smoothDnD } from '@farris/smooth-dnd';
import { DomService, DesignViewModelService, FormBasicService, SchemaService, RefreshFormService, DgControl } from '@farris/designer-services';


/**
 * 维护Form控件下的输入控件。TODO：暂时屏蔽运行时定制新增的be字段
 */
@Component({
  selector: 'app-field-manager',
  templateUrl: './field-manager.component.html',
  styleUrls: ['./field-manager.component.css'],
  providers: [FieldTreeTableService]
})

export class FieldManagerComponent implements OnInit, AfterViewInit, OnDestroy {
  /** 卡片所属的视图模型id */
  @Input() viewModelId;

  /** 卡片所属的Form 控件id，用于点击确定后重绘卡片区域 */
  @Input() formId;

  /** 点击取消，关闭窗口 */
  @Output() closeModal = new EventEmitter<any>();

  /** 点击确定，关闭窗口 */
  @Output() confirmModal = new EventEmitter<any>();


  /** 页脚按钮 */
  @ViewChild('modalFooter') modalFooter: TemplateRef<any>;

  idField = 'id';

  @ViewChild('leftTree') leftTree: TreeTableComponent;
  leftTreeData: TreeNode[] = [];

  @ViewChild(FieldTreeTableComponent) rightCmp: FieldTreeTableComponent;
  viewModelFieldChanges = {};


  /** 记录初始字段ID列表 */
  initRightFieldIds = [];

  /** 组件是否支持分组：只有form类型组件支持分组 */
  canGroup = true;
  noDataMoveMessage = '请选择要移动的数据。';

  dgVMServ: DesignViewModelService;
  domServ: DomService;
  fieldTreeServ: FieldTreeTableService;

  /** 运行时定制追加的字段节点(be或vo中新追加，但是表单schema中没有的) */
  rtAddedTreeNodes = [];

  /** 当前卡片中是否允许再次添加其他卡片中已使用的字段。若不允许，则置灰处理  */
  disableFieldsInOtherForm = true;

  /** 在其他卡片中已使用的字段id */
  fieldIdsInOhterForms = [];

  constructor(
    private notifyServ: NotifyService,
    private injector: Injector,
    private ngZone: NgZone,
    private cd: ChangeDetectorRef,
    private formBasicServ: FormBasicService,
    // private rtSchemaServ: RtSchemaService,
    private schemaServ: SchemaService,
    private refreshFormService: RefreshFormService) {

    this.dgVMServ = this.injector.get(DesignViewModelService);
    this.domServ = this.injector.get(DomService);
    this.fieldTreeServ = this.injector.get(FieldTreeTableService);
  }

  @HostBinding('class')
  cls = 'row f-multi-select h-100 p-2';
  ngOnInit() {
    this.getFieldIdsInOtherForms();
    this.initData();
    this.subscribeViewModelChanged();
  }
  ngAfterViewInit() {
    this.ngZone.runOutsideAngular(() => {
      setTimeout(() => {
        this.makeSourceTreeDraggable();
      });
    });
    this.rightCmp.addFieldDropped.subscribe(() => {
      this.leftTree.clearAll();

      this.cd.detectChanges();
    });
  }
  ngOnDestroy() {
    if (this['leftTreeContainer']) {
      this['leftTreeContainer'].dispose();
    }
  }

  initData() {
    const cmp = this.domServ.getComponentByVMId(this.viewModelId);

    this.leftTreeData = this.dgVMServ.getAllFields2TreeByVMId(this.viewModelId);

    // 运行时定制追加字段
    // if (this.formBasicServ.envType === DesignerEnvType.runtimeCustom && this.rtSchemaServ.addedTreeNodes) {
    //     const entityInfo = this.schemaServ.getTableInfoByViewModelId(this.viewModelId);
    //     if (entityInfo) {
    //         this.rtAddedTreeNodes = this.rtSchemaServ.addedTreeNodes[entityInfo.id];
    //         if (this.rtAddedTreeNodes) {
    //             this.leftTreeData = this.leftTreeData.concat(this.rtAddedTreeNodes);
    //         }
    //     }
    // }

    this.ngZone.runOutsideAngular(() => {
      setTimeout(() => {
        this.initRightFieldIds = this.rightCmp.treeTable.serializedValue.map(v => v.node.data.id);
      });
    });


    this.canGroup = cmp.componentType.startsWith('form') || this.formBasicServ.envType === 'mobileDesigner';
  }
  /**
   * 获取在其他卡片中已使用的字段id，这些字段在当前卡片中不允许再添加
   */
  private getFieldIdsInOtherForms() {
    this.fieldIdsInOhterForms = [];
    const currentVM = this.domServ.getViewModelById(this.viewModelId);
    const currentCmp = this.domServ.getComponentByVMId(this.viewModelId);
    /** 当前组件的类型 */
    let currentComponentType = currentCmp.componentType;

    // 根组件和table组件内的输入控件与form内不能重复
    if (currentCmp.componentType === 'Frame' || currentCmp.componentType === 'table' || (currentCmp.componentType && currentCmp.componentType.startsWith('form'))) {
      currentComponentType = 'form';
    }
    this.domServ.viewmodels.forEach(vm => {

      // 绑定同一个实体
      if (vm.id === this.viewModelId || !vm.fields || !vm.fields.length || vm.bindTo !== currentVM.bindTo) {
        return;
      }
      const cmpNode = this.domServ.getComponentByVMId(vm.id);

      let componentType = cmpNode.componentType;
      if (componentType === 'Frame' || componentType === 'table' || (componentType && componentType.startsWith('form'))) {
        componentType = 'form';
      }

      if (currentComponentType === componentType && !this.checkIfInSidebar(cmpNode)) {
        const fieldIds = vm.fields.map(f => f.id);
        this.fieldIdsInOhterForms = this.fieldIdsInOhterForms.concat(fieldIds);
      }

    });


  }
  /**
   * 监听树组件的字段变化，组合viewModel字段schema的增量
   */
  subscribeViewModelChanged() {
    this.rightCmp.viewModelChanged.subscribe(changes => {
      Object.assign(this.viewModelFieldChanges, changes);
    });
  }


  canChecked(item: any) {


    const data = item.data;

    if (item.selectable !== undefined && !item.selectable) {
      return false;
    }
    const rightTree = this.rightCmp.treeTable;
    const rightTreeData = this.rightCmp.treeData;
    const isInOtherForm = this.fieldIdsInOhterForms.find(id => id === data[this.idField]);
    if (this.disableFieldsInOtherForm && isInOtherForm) {
      return false;
    }
    if (!rightTreeData || rightTreeData.length === 0) {
      return true;
    } else {
      const serializedData = rightTree.serializedValue.map(s => s.node.data);
      return serializedData.findIndex(c => c[this.idField] === data[this.idField]) === -1;
    }


  }

  /**
   * 新增字段
   */
  moveToRight() {
    const leftChecks = this.leftTree.checkeds;
    if (!leftChecks || leftChecks.length === 0) {
      this.notifyServ.warning(this.noDataMoveMessage);
      return;
    }
    // const fields = leftChecks.map(c => c.data);
    this.rightCmp.addFields(leftChecks);

    this.leftTree.clearAll();
  }

  /**
   * 全部新增
   */
  moveAllToRight() {
    const leftChecks = [];
    this.leftTree.serializedValue.forEach(rn => {
      if (rn.node.selectable) {
        if (this.canChecked(rn.node)) {
          leftChecks.push(rn.node);
        }
      }
    });

    this.rightCmp.addFields(leftChecks);

    this.leftTree.clearAll();
  }

  /**
   * 删除字段
   */
  moveToLeft() {
    this.rightCmp.removeFields();

  }
  /**
   * 全部删除
   */
  moveAllToLeft() {
    this.rightCmp.removeAllFields();
  }


  /**
   * 置顶
   */
  moveTop() {
    this.rightCmp.moveTop();

  }
  /**
   * 上移
   */
  moveUp() {
    this.rightCmp.moveUp();
  }
  /**
   * 下移
   */
  moveDown() {
    this.rightCmp.moveDown();
  }

  /**
   * 置底
   */
  moveBottom() {
    this.rightCmp.moveBottom();
  }

  addGroup() {
    this.rightCmp.addGroup();
  }
  removeGroup() {
    this.rightCmp.removeGroup();
  }

  clickCancel() {
    this.closeModal.emit();
  }

  clickOK() {
    this.fieldTreeServ.refreshDOM(this.viewModelId, this.rightCmp.treeData);

    const dgVM = this.dgVMServ.getDgViewModel(this.viewModelId);



    const addedFields = [];
    const currentFieldIds = [];
    // 增加字段
    this.rightCmp.treeTable.serializedValue.forEach(row => {
      const node = row.node as TreeNode | any;
      if (node.isGroupNode) {
        return;
      }
      if (!this.initRightFieldIds.includes(node.data.id)) {

        dgVM.addField(node.data);

        // 运行时定制新同步的be或vo字段
        // addedFields.push(node.data); 可以在ui中处理新增的字段
        // if (this.formBasicServ.envType === DesignerEnvType.runtimeCustom && this.rtAddedTreeNodes) {
        //     const addedFieldId = node.rtRelateSchemaField ? node.rtRelateSchemaField.id : node.id;
        //     const treeNode = this.rtAddedTreeNodes.find(n => n.id === addedFieldId);

        //     if (treeNode) {
        //         this.rtSchemaServ.createNewSchemaField(this.viewModelId, treeNode.data);
        //     }
        // }
      }
      currentFieldIds.push(node.data.id);
    });

    // 删除字段
    const deletedFieldIds = this.initRightFieldIds.filter(id => !currentFieldIds.includes(id));
    dgVM.removeField(deletedFieldIds);



    // 修改字段
    const fieldIdList = Object.keys(this.viewModelFieldChanges);
    if (fieldIdList.length > 0) {

      fieldIdList.forEach(fieldId => {
        const vmChange = this.viewModelFieldChanges[fieldId];
        dgVM.changeField(fieldId, vmChange);
      });
    }
    // 刷新设计器页面
    this.refreshFormService.refreshFormDesigner.next(this.formId);

    // 关闭窗口
    this.confirmModal.emit({
      addedFields,
      deletedFieldIds
    });
  }


  /**
   * 配置左侧树可拖拽
   */
  private makeSourceTreeDraggable() {
    const tbodyList = this.leftTree.el.nativeElement.getElementsByTagName('tbody');
    if (!tbodyList.length) {
      return;
    }
    const containerElement = tbodyList[0];
    const containerOptions: ContainerOptions = {
      behaviour: 'copy',
      getGhostParent: this.getGhostParent,
      groupName: 'selectColumn',
      nonDragAreaSelector: '[ng-reflect-select-row-disabled=true]',
      getChildPayload: this.getSourceTreeChildPayload.bind(this)
    };
    // tslint:disable-next-line:no-string-literal
    this['leftTreeContainer'] = smoothDnD(containerElement, containerOptions);
    const children = containerElement.children;

    Array.prototype.forEach.call(children, (item: HTMLElement) => {
      item.classList.add(constants.wrapperClass);
    });
  }


  private getGhostParent() {
    return window.document.body;
  }

  private getSourceTreeChildPayload(index: number) {
    return this.leftTree.serializedValue[index].node.data;
  }

  /**
   * 左侧树搜索
   */
  searchField($event) {
    if ($event) {
      const { field, value } = $event;
      this.leftTree.searchHandle.search(field, value);
    } else {
      this.leftTree.searchHandle.search('*', '');
    }
    // 重新触发左侧树的拖拽渲染
    this.ngZone.runOutsideAngular(() => {
      setTimeout(() => {
        this.makeSourceTreeDraggable();
      });
    });
  }


  /**
   * 检查卡片组件是否在侧边栏中，在侧边栏中的字段可以与非侧边栏中的字段重复。
   */
  private checkIfInSidebar(cmpNode: any) {

    const sidebar = this.domServ.selectNode(this.domServ.components[0],
      item => item.type === DgControl.Sidebar && DgControl.Sidebar.type && item.contents && item.contents.length &&
        item.contents.find(child => child.type === DgControl.ComponentRef.type && child.component === cmpNode.id));
    if (sidebar) {
      return true;
    }
    return false;
  }
}
